import os 
import shutil
import os
OPENSLIDE_PATH = r'C:\openslide-win64-20231011\bin'
if hasattr(os, 'add_dll_directory'):
    # Windows
    with os.add_dll_directory(OPENSLIDE_PATH):
        import openslide
else:
    import openslide

import numpy as np 
import cv2
import xml.etree.ElementTree as ET
import tqdm
import threading
import copy
import concurrent.futures
path=r'/media/doge/UBUNTU 22_0/01.07'
spath=r'dataset_yolov8_predictions'
if not os.path.exists(spath):
    os.makedirs(spath)
image_path=os.path.join(spath,'images')
label_path=os.path.join(spath,'labels')
if os.path.exists(image_path):
    shutil.rmtree(image_path)
if os.path.exists(label_path):
    shutil.rmtree(label_path)
os.makedirs(image_path)
os.makedirs(label_path)

def edge_detect(xyxy_in_region,index_x,index_y,tile_size):
    for xyxy in xyxy_in_region:
        for xy in xyxy[:2]:
            if (not (index_x<xy[0]<index_x+tile_size) )or (not index_y<xy[1]<index_y+tile_size ):
                return False 
    return True


def process_and_save_image(slide,index_x,index_y,tile_size,xyxy_in_region,pic_index,ndpi_name):
    region = slide.read_region((index_x, index_y), 0, (tile_size, tile_size))

    with open(os.path.join(label_path,f'{str(pic_index).zfill(4)}_{ndpi_name}_{index_x}_{index_y}.txt'), 'w') as f:
        for xyxy in xyxy_in_region:
            if xyxy[2]== 1:
                x = xyxy[0][0] - index_x
                y = xyxy[0][1] - index_y
                w = xyxy[1][0] - xyxy[0][0]
                h = xyxy[1][1] - xyxy[0][1]
                yolo_x = int(x + w/2) / tile_size
                yolo_y = int(y + h/2) / tile_size
                yolo_w = w / tile_size
                yolo_h = h / tile_size
                f.write(f'0 {yolo_x} {yolo_y} {yolo_w} {yolo_h}\n')
    f.close()
    image_name=os.path.join(image_path,f'{str(pic_index).zfill(4)}_{ndpi_name}_{index_x}_{index_y}.png')
    print(image_name)
    region.save(image_name)

pic_index = 0
for i in tqdm.tqdm(os.listdir(path)):
    # print (i)
    if i.endswith('xml'):
        print (i)
        path1=os.path.join(path,i)
        

        train=i.split('\\')[-1][:-4]+'.ndpi'
        # print(i,img)
        # print(s1)
        img=os.path.join(path,train)


        # print(img,mask)
        # print(s2)
        slide = openslide.open_slide(img)
        width, height = slide.dimensions
#         # print(slide.dimensions)
#     # # # 定义每个小病理切片的大小
        tree = ET.parse(path1)
        root = tree.getroot()
        
        annotation1 =  list(root.iter('Annotation'))[0]


        # draw cells
        xyxy_list = []
        for region in annotation1.iter('Region'):
            if region.get('Text') == '1' or region.get('Text') == '0':
                list1=[]
                for vertex in region.iter('Vertex'):
                    x = vertex.get('X')
                    y = vertex.get('Y')
                    list1.append([int(float(x)),int(float(y))])
                list_xyxy = [[list1[0][0],list1[0][1]],[list1[2][0],list1[2][1]],int(region.get('Text'))]
                xyxy_list.append(copy.deepcopy(list_xyxy))

        

        tile_size = 640
        index_x = 0
        index_y = 0
        
        with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
            threads = []
            while True:

                while True:

                
                    # 获取当前小病理切片的区域
                    
                    while True:
                        # print (index_x,index_y,width,height)
                        xyxy_in_region = []
                        for xyxy in xyxy_list:
                            for xy in xyxy[:2]:

                                if index_x<xy[0]<index_x+tile_size and index_y<xy[1]<index_y+tile_size:
                                    xyxy_in_region.append(xyxy)
                                    break

                        if len(xyxy_in_region)==0:
                            break
                        if edge_detect(xyxy_in_region,index_x,index_y,tile_size):
                            # print (index_x,index_y,xyxy_in_region)
                            # process_and_save_image(slide,index_x,index_y,tile_size,xyxy_in_region,pic_index)
                            t = executor.submit(process_and_save_image,slide,index_x,index_y,tile_size,xyxy_in_region,pic_index,i.split('\\')[-1][:-4])
                            threads.append(t)
                            print (pic_index)
                            pic_index+=1
                            break
                        else:
                            index_y+=100
                            index_x+=100
                            if (index_x +tile_size > width ):
                                break
                    
                    index_x += tile_size
                    if (index_x +tile_size > width ):
                        index_x=0
                        break
                index_y += tile_size
                if (index_y + tile_size > height ):
                    break
        concurrent.futures.wait(threads)
        slide.close()
            
